package task2_2;

import java.util.List;
import java.util.ArrayList;

/**
 * Created by IntelliJ IDEA.
 * User: ATroshanin
 * Date: 01.06.2006
 * Time: 16:51:55
 * To change this template use File | Settings | File Templates.
 */
public class TaskCounter {

    private List lexems;

    private List stackSost;

    String [][] gramaTab = {
            {"viraj",   "digit"    ,   "znak"  ,   "viraj"},
            {"viraj",   "digit"    ,   "###"   ,   "###"},
            {"viraj",   "("        ,   "viraj" ,   ")"},
    };

    public TaskCounter(List lexems) {
        this.lexems = lexems;
        int a;
        a = 5;
    }

    public List Polsk() {

        if (!testCorrectHard(lexems)) {
            return null;
        }

        List resultStack = new ArrayList();
        stackSost = new ArrayList();

        for (int i=0; i<lexems.size(); i++) {
            Object lexObj = lexems.get(i);
            Lexem lex = (Lexem) lexems.get(i);

            if (lex.getType().equals(Lexem.TYPE_DIGIT)) {
                resultStack.add(lex);
            } else if (lex.getType().equals(Lexem.TYPE_ZNAK)) {

                if (lex.getValue().equals("+") || lex.getValue().equals("-")) {
                    if (stackSost.size() == 0) {
                        stackSost.add(lex);
                    } else {
                        while (stackSost.size() != 0 && !((Lexem) stackSost.get(stackSost.size() - 1)).getValue().equals("(")) {
                            Lexem curLastLex = (Lexem) stackSost.get(stackSost.size() - 1);
                            stackSost.remove(stackSost.size() - 1);
                            resultStack.add(curLastLex);
                        }
                        stackSost.add(lex);
                    }
                } else if (lex.getValue().equals("*") || lex.getValue().equals("/")) {
                    if (stackSost.size() == 0) {
                        stackSost.add(lex);
                    } else {
                        Lexem lastLex = (Lexem) stackSost.get(stackSost.size() - 1);
                        if (lastLex.getValue().equals("+") || lastLex.getValue().equals("-") || lastLex.getValue().equals("(")) {
                            stackSost.add(lex);
                        } else {
                            stackSost.remove(stackSost.size() - 1);
                            resultStack.add(lastLex);
                            stackSost.add(lex);
                        }
                    }
                } else if(lex.getValue().equals("(")){
                     stackSost.add(lex);
                } else if(lex.getValue().equals(")")){
                    while (stackSost.size() != 0 && !((Lexem) stackSost.get(stackSost.size() - 1)).getValue().equals("(")) {
                        Lexem curLastLex = (Lexem) stackSost.get(stackSost.size() - 1);
                        stackSost.remove(stackSost.size() - 1);
                        resultStack.add(curLastLex);
                    }
                    if (stackSost.size() > 0) {
                        stackSost.remove(stackSost.size() - 1);
                    } else {
                        return null;
                    }
                }
            } else {
                return null;
            }
        }

        while (stackSost.size() != 0 && !((Lexem) stackSost.get(stackSost.size() - 1)).getValue().equals("(")) {
            Lexem curLastLex = (Lexem) stackSost.get(stackSost.size() - 1);
            stackSost.remove(stackSost.size() - 1);
            resultStack.add(curLastLex);
        }
        if (stackSost.size() > 0) {
            return null;
        }

        return resultStack;
    }

    public List polsk2() {

        List resultStack = new ArrayList();
        stackSost = new ArrayList();

        for (int i=0; i<lexems.size(); i++) {
            Object lexObj = lexems.get(i);
            Lexem lex = (Lexem) lexems.get(i);

            if (lex.getType().equals(Lexem.TYPE_NUMBER)) {
                resultStack.add(lex);
            } else if (lex.getType().equals(Lexem.TYPE_TERM)) {
                resultStack.add(lex);
            } else if (lex.getType().equals(Lexem.TYPE_FUNCTION)) {
                stackSost.add(lex);
            } else if (lex.getType().equals(Lexem.TYPE_ZNAK)) {

                if (lex.getValue().equals("+") || lex.getValue().equals("-")) {
                    if (stackSost.size() == 0) {
                        stackSost.add(lex);
                    } else {
                        while (stackSost.size() != 0 && !((Lexem) stackSost.get(stackSost.size() - 1)).getValue().equals("(")) {
                            Lexem curLastLex = (Lexem) stackSost.get(stackSost.size() - 1);
                            stackSost.remove(stackSost.size() - 1);
                            resultStack.add(curLastLex);
                        }
                        stackSost.add(lex);
                    }
                } else if (lex.getValue().equals("*") || lex.getValue().equals("/")) {
                    if (stackSost.size() == 0) {
                        stackSost.add(lex);
                    } else {
                        Lexem lastLex = (Lexem) stackSost.get(stackSost.size() - 1);
                        if (lastLex.getValue().equals("+") || lastLex.getValue().equals("-") || lastLex.getValue().equals("(")) {
                            stackSost.add(lex);
                        } else {
                            stackSost.remove(stackSost.size() - 1);
                            resultStack.add(lastLex);
                            stackSost.add(lex);
                        }
                    }
                } else if(lex.getValue().equals("(")){
                     stackSost.add(lex);
                } else if(lex.getValue().equals(")")){
                    while (stackSost.size() != 0 && !((Lexem) stackSost.get(stackSost.size() - 1)).getValue().equals("(")) {
                        Lexem curLastLex = (Lexem) stackSost.get(stackSost.size() - 1);
                        stackSost.remove(stackSost.size() - 1);
                        resultStack.add(curLastLex);
                    }
                    if (stackSost.size() > 0) {
                        stackSost.remove(stackSost.size() - 1);
                    } else {
                        return null;
                    }
                }
            } else {
                return null;
            }
        }

        while (stackSost.size() != 0 && !((Lexem) stackSost.get(stackSost.size() - 1)).getValue().equals("(")) {
            Lexem curLastLex = (Lexem) stackSost.get(stackSost.size() - 1);
            stackSost.remove(stackSost.size() - 1);
            resultStack.add(curLastLex);
        }
        if (stackSost.size() > 0) {
            return null;
        }

        return resultStack;
    }

    private boolean testCorrect() {

        int sost = 1;
        String curSost = "viraj";
        for (int i=0; i<lexems.size(); i++) {
            Lexem lex = (Lexem) lexems.get(i);

            if (lex.getType().equals(Lexem.TYPE_DIGIT)) {
                for (int k=0;k<gramaTab.length; k++) {

                    if (gramaTab[k][sost].equals("digit")) {
                        sost++;
                        continue;
                    }
                    return false;
                }
            } else if (lex.getValue().equals("+") || lex.getValue().equals("-") || lex.getValue().equals("*") || lex.getValue().equals("/")) {
                for (int k=0;k<gramaTab.length; k++) {
                    if (gramaTab[k][sost].equals("znak")) {
                        sost++;
                        continue;
                    }
                    return false;
                }
            } else if (lex.getValue().equals("(") ) {
                for (int k=0;k<gramaTab.length; k++) {

                    if (gramaTab[k][sost].equals("digit")) {
                        sost++;
                        continue;
                    }
                    return false;
                }
            }

        }

        return true;
    }

    private boolean testCorrectHard(List lexs) {

        String sost = "nothing";
        for (int i=0; i<lexs.size(); i++) {
            Lexem lex = (Lexem) lexs.get(i);

            if (lex.getType().equals("digit")) {
                if (sost.equals(")")) {
                    return false;
                }
                sost = "digit";
            } else if(lex.getValue().equals("+") || lex.getValue().equals("-") || lex.getValue().equals("*") || lex.getValue().equals("/")) {

                if (sost.equals("nothing") || sost.equals("znak")) {
                    return false;
                }
                sost = "znak";
            } else if(lex.getValue().equals("(")) {

                List subLst = new ArrayList();
                int k = i+1;
                int skobkaCount=0;
                while (k < lexs.size() && (!((Lexem)lexs.get(k)).getValue().equals(")") || skobkaCount>0 )) {
                    if (((Lexem)lexs.get(k)).getValue().equals("(")) {
                        skobkaCount++;
                    }
                    if (((Lexem)lexs.get(k)).getValue().equals(")")) {
                        skobkaCount--;
                    }
                    subLst.add(lexs.get(k));
                    k++;
                }
                if (k == lexs.size()) {
                    return false;
                }
                if (!testCorrectHard(subLst)) {
                    return false;
                }

                i = k + 1;

            } else if(lex.getValue().equals(")")) {
                return false;
            }

        }
        return true;
    }

}
